[Ruby on Rails]sorceryによる認証 – (3)メールによるアクティベーション
はじめに
以前の記事に引き続きsorceryによる認証についてです。今回はアカウントの作成時にメールを送信し、リンクをクリックしたらアカウントを有効化する、アクティベーションを実装してみました。
なお今回はsorceryで認証ができるアプリに、機能を追加する形で実装していきます。予め以下などを参考にemail、passwordでアカウントを登録できるアプリを作成しておいてください。
公式チュートリアル
以前の記事
アクティベーションの画面フロー
今回作成する機能のイメージを掴みやすくするため、画面のスクリーンショットを遷移順に貼っておきます。
1.アカウントの作成
「New User」をクリックし、アカウント作成画面を表示します。
2.アカウント作成
「Email」「Password」を入力して登録します。
3.アカウント登録完了
登録されたアカウントが一覧に表示されます。ここまではアクティベーションの有無に関わらず(画面上は)同じ動きとなります。
4.メールによるアクティベーション前でのログイン
この時点でアクティベーションのためのメールが送られている筈ですが、敢えてそのメールを見る前にログインしてみます。するとログインは失敗します。
5.アクティベーションのためのメール
アカウント作成時に入力したメールアドレスに、アクティベーションを行う為のメールが送られてきます。「To login to the site,・・・」以降のリンクをクリックすると、次のアクティベーション成功の画面が表示されます。
6.アクティベーション成功
メールのリンクをクリックすると、アクティベーションが行われ、成功した旨のメッセージが表示されます。
7.アクティベーション成功メール
上記と同時に、アクティベーションが成功した旨のメールも送られてきます。
8.ログイン成功
アクティベーション後にログインすると、ログインが成功します。
アプリケーションの実装
では実装についてです。今回も公式チュートリアルをなぞりましたが、幾つか追加したり変更した手順もありますので合わせて紹介したいと思います。
1.「user_activation」サブモジュールのインストール
sorceryは追加可能な機能を、それぞれサブモジュールの形で提供しています。今回はアクティベーションを行うのに「user_activation」サブモジュールが必要なので、これをインストールします。以下のコマンドを実行してください。
$ rails g sorcery:install user_activation --only-submodules
以下のようなマイグレーションファイルが作成されます。
class SorceryUserActivation < ActiveRecord::Migration def self.up add_column :users, :activation_state, :string, :default => nil add_column :users, :activation_token, :string, :default => nil add_column :users, :activation_token_expires_at, :datetime, :default => nil add_index :users, :activation_token end def self.down remove_index :users, :activation_token remove_column :users, :activation_token_expires_at remove_column :users, :activation_token remove_column :users, :activation_state end end
マイグレーションを実行してDBに反映します。
$ rake db:migrate
またsorceryの定義ファイルに、使用するサブモジュールとして「user_activation」が追加されていることを確認してください(無ければ追加してください)。
config/initializers/sorcery.rb
Rails.application.config.sorcery.submodules = [:user_activation, ・・・
2.ActionMailerの作成
アクティベーションのメールを送信するため、RailsのActionMailerを使用します。以下のコマンドで、ActionMailerのテンプレートを作成します。
$ rails g mailer UserMailer activation_needed_email activation_success_email
sorceryの定義ファイルにアクティベーションで使用するActionMailerとして、上記で作成したUserMailerを定義します。
config/initializers/sorcery.rb
config.user_config do |user| (中略) user.user_activation_mailer = UserMailer (中略) end
アクティベーション時のメールと、アクティベーション成功時のメールを定義します。
app/mailers/user_mailer.rb
def activation_needed_email(user) @user = user @url = "http://0.0.0.0:3000/users/#{user.activation_token}/activate" mail(:to => user.email, :subject => "Welcome to My Awesome Site") end def activation_success_email(user) @user = user @url = "http://0.0.0.0:3000/login" mail(:to => user.email, :subject => "Your account is now activated") end
app/views/user_mailer/activation_needed_email.text.erb
Welcome to example.com, <%= @user.email %> =============================================== You have successfully signed up to example.com, your email is: <%= @user.email %>. To login to the site, just follow this link: <%= @url %>. Thanks for joining and have a great day!
app/views/user_mailer/activation_success_email.text.erb
Congratz, <%= @user.email %> =============================================== You have successfully activated your example.com account, your email is: <%= @user.email %>. To login to the site, just follow this link: <%= @url %>. Thanks for joining and have a great day!
公式のチュートリアルではユーザ名(user.username)を参照していましたが、今回はユーザ名は保持していないため、全てメールアドレス(email)に変更しています。またテキスト形式でのフォーマットのみ定義しているため、HTML形式のフォーマットファイル(app/views/user_mailer/〜.html.erb)は削除しました。
3.アクティベーションを行うアクションを定義
アクティベーションを行うアクションを、コントローラに定義します。
app/controllers/users_controller.rb
skip_before_filter :require_login, :only => [:index, :new, :create, :activate] def activate if (@user = User.load_from_activation_token(params[:id])) @user.activate! redirect_to(login_path, :notice => 'User was successfully activated.') else not_authenticated end end
ルーティングも上記アクションを呼び出せるように変更します。
config/routes.rb
resources :users do member do get :activate end end
4.ActionMailerの定義
公式のチュートリアルはここまでの手順しか載っていませんが、実際にメールを送信するにはSMTPの定義が必要です。今回はgmailを使用したので、以下の様な定義を行いました。2段階認証を使用している場合、gmailのアカウントのパスワードと、アプリケーション固有のパスワードの2つを定義することに注意してください。
config/environments/development.rb
config.action_mailer.delivery_method = :smtp config.action_mailer.raise_delivery_errors = true config.action_mailer.smtp_settings = { :enable_starttls_auto => true, :address => 'smtp.gmail.com', :port => '587', :domain => 'smtp.gmail.com', :authentication => 'plain', :user_name => 'ユーザ名', :password => 'パスワード', :password => 'アプリケーション固有のパスワード' }
まとめ
以上のように非常に簡単にアクティベーションを実装することができました。メールの送信にはActionMailerを使用するなどRailsとの親和性も高く、使いやすいように思います。
参考サイト
以下のサイトを参考にさせて頂きました。ありがとうございました。
Simple Password Authentication
User Activation
RailsのActionMailerでメールを送信する(Gmail経由)
Googleで2段階認証を使っているときにRailsのActionMailerでGmailを使う方法